﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using LocalFx;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


namespace mirror
{
    public class cPostProcFx
    {
        protected Effect mFx;
        protected float currentTime;
        protected Texture2D inputTex;

        public virtual String fxName() {return "";}

        public virtual void LoadContent(ContentManager content, GraphicsDevice device)
        {
            currentTime = 0.0f;
            mFx = content.Load<Effect>(fxName());
        }

        public void SetInput(Texture2D tex)
        {
            inputTex = tex;
        }

        public virtual void Update(GameTime gametime)
        {
            if(gametime != null)
                currentTime += (float)gametime.ElapsedGameTime.TotalSeconds;
            mFx.Parameters["View"].SetValue(Camera.Instance.ViewMatrix);
            mFx.Parameters["Projection"].SetValue(Camera.Instance.ProjectionMatrix);
            if(inputTex != null)
                mFx.Parameters["Texture"].SetValue(inputTex);

        }

        public virtual void Render()
        {
            cRenderManager.Instance.Device().BlendState = BlendState.Opaque;
            cRenderManager.Instance.Device().DepthStencilState = DepthStencilState.None;
            cRenderManager.Instance.RenderQuad(mFx, 1);
        }

        public virtual bool Alive()
        {
            return true;
        }
    }

    public class cThudPostProc : cPostProcFx
    {
        Vector3 mPos;
        bool mAlive;
        float mDuration;
        float mIntensity;
        float mRadius;

        public override String fxName() {return "SSWobble";}

        public void Start(Vector3 pos, float intensity, float radius,float duration)
        {
            mAlive = true;
            mPos = pos;
            mDuration = duration;
            mIntensity = intensity;
            mRadius = radius;
        }

        public override void Update(GameTime gametime)
        {
            base.Update(gametime);

            Vector4 sspos;
            sspos.X = mPos.X;
            sspos.Y = mPos.Y;
            sspos.Z = mPos.Z;
            sspos.W = 1.0f;

            //sspos = Vector4.Transform(sspos, Matrix.Transpose(Camera.Instance.ViewMatrix));
            //sspos = Vector4.Transform(sspos, Matrix.Transpose(Camera.Instance.ProjectionMatrix));

            sspos = Vector4.Transform(sspos, Camera.Instance.ViewMatrix);
            sspos = Vector4.Transform(sspos, Camera.Instance.ProjectionMatrix);

            sspos.X /= sspos.W;
            sspos.Y /= sspos.W;

            sspos.X = sspos.X * 0.5f + 0.5f;
            sspos.Y = 1.0f - (sspos.Y * 0.5f + 0.5f);

            mFx.Parameters["age"].SetValue(currentTime / mDuration);
            mFx.Parameters["intensity"].SetValue(mIntensity);
            mFx.Parameters["radius"].SetValue(mRadius);
            mFx.Parameters["waves_per_second"].SetValue(mRadius*10);
            mFx.Parameters["ctc"].SetValue(sspos);

            if (mDuration < currentTime)
                mAlive = false;
        }

        public override bool Alive()
        {
            return mAlive;
        }
    }

    public class cBlitPostProc : cPostProcFx
    {
        public override String fxName() {return "Blit";}
    }

    public class cContrastPostProc : cPostProcFx
    {
        bool mAlive;
        float mDuration;
        float mIntensity;
        float mThreshold;

        public override String fxName() { return "Contrast"; }

        public void Start(float threshold,float intensity, float duration)
        {
            currentTime = 0.0f;
            mAlive = true;
            mDuration = duration;
            mIntensity = intensity;
            mThreshold = threshold;
        }

        public override void Update(GameTime gametime)
        {
            base.Update(gametime);

            mFx.Parameters["age"].SetValue(currentTime / mDuration);
            mFx.Parameters["intensity"].SetValue(mIntensity);
            mFx.Parameters["threshold"].SetValue(mThreshold);

            if (mDuration < currentTime)
                mAlive = false;
        }

        public override bool Alive()
        {
            return mAlive;
        }

         public override void Render()
         {
             cRenderManager.Instance.Device().DepthStencilState = DepthStencilState.DepthRead;
             cRenderManager.Instance.RenderQuad(mFx, 1);
         }
    }

    public class cColorFilterPostProc : cPostProcFx
    {
        bool mAlive = true;
        float mChangeDuration = 0.25f;
        float mRedBlueLerp = 0.0f;
        Texture2D mNoiseTex;

        public override String fxName() { return "ColorFilter"; }

        public void Start(float redBlueLerp, float duration)
        {
            currentTime = 0.0f;
            mAlive = true;
            mChangeDuration = duration;
            mRedBlueLerp = redBlueLerp;
        }

        public override void Update(GameTime gametime)
        {
            base.Update(gametime);

            float t = Math.Min(currentTime / mChangeDuration, 1.0f);
            float redBlueLerp = (1 - t) * mRedBlueLerp + t * (1 - mRedBlueLerp);
            mFx.Parameters["redBlueLerp"].SetValue(redBlueLerp);
            mFx.Parameters["TextureNoise"].SetValue(mNoiseTex);
        }

        public override void LoadContent(ContentManager content, GraphicsDevice device)
        {
            base.LoadContent(content, device);
            mNoiseTex = content.Load<Texture2D>("random4");
        }

        public override bool Alive()
        {
            return true;
        }

        public override void Render()
        {
            cRenderManager.Instance.Device().BlendState = BlendState.Opaque;
            cRenderManager.Instance.Device().DepthStencilState = DepthStencilState.DepthRead;
            cRenderManager.Instance.RenderQuad(mFx, 1);
        }
    };
}
